package com.google.code.irouter.batch;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.appengine.api.datastore.DatastoreFailureException;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.code.irouter.batch.api.DetectorResult;
import com.google.code.irouter.batch.getter.InfoGetter;
import com.google.code.irouter.model.Collector;
import com.google.code.irouter.model.Consumer;
import com.google.code.irouter.model.Guide;
import com.google.code.irouter.model.History;
import com.google.code.irouter.model.Model;
import com.google.code.irouter.model.Queue;
import com.google.code.irouter.model.Relationship;
import com.google.code.irouter.model.Transponder;
import com.google.code.irouter.utils.DateTimeUtil;
import com.google.code.irouter.utils.LocalUtil;
import com.google.code.irouter.utils.LogUtil;
import com.google.code.irouter.utils.ModelUtil;

public final class Getter {

	private static Date lastScan = null;

	public static void execute() {
		if (lastScan == null)
			lastScan = DateTimeUtil.getNow();

		Query queryGuide = new Query(Guide.class.getSimpleName());
		queryGuide.addFilter("lastScan", FilterOperator.NOT_EQUAL, lastScan);
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();
		PreparedQuery preparedQuery = datastore.prepare(queryGuide);
		Iterator<Entity> entityIterator = preparedQuery.asIterator();
		if (!entityIterator.hasNext()) {
			lastScan = DateTimeUtil.getNow();
			return;
		}
		Entity entity = entityIterator.next();
		Guide guide = new Guide();
		guide.parse(entity);
		guide.setLastScan(lastScan);
		ModelUtil.save(guide);
		List<DetectorResult> results = InfoGetter.execute(guide);
		
		Map<String, Object> query = new HashMap<String, Object>();
		query = new HashMap<String, Object>();
		query.put("guides", guide.getKey());
		List<Model> modelCollectorList = ModelUtil.select(Collector.class, query);
		for (Model modelCollector : modelCollectorList) {
			Collector collector = (Collector) modelCollector;
			query = new HashMap<String, Object>();
			query.put("collector", collector.getKey());
			List<Model> modelRelationshipList = ModelUtil.select(Relationship.class, query);
			for (Model modelRelationship : modelRelationshipList) {
				Relationship relationship = (Relationship) modelRelationship;
				List<Model> modelTransponderList = ModelUtil.select(Transponder.class, relationship.getTransponder());
				for (Model modelTransponder : modelTransponderList) {
					Transponder transponder = (Transponder) modelTransponder;
					Set<Key> keySet = transponder.getConsumers();
					for (Key key : keySet) {
						List<Model> modelConsumerList = ModelUtil.select(Consumer.class, key);
						if (modelConsumerList.size() == 0)
							continue;
						Consumer consumer = (Consumer) modelConsumerList.get(0);
						
						for(DetectorResult result : results) {
							query = new HashMap<String, Object>();
							query.put("content", result.getMessage());
							query.put("solution", relationship.getSolution());
							query.put("relationship", relationship.getKey());
							if(ModelUtil.select(History.class, query).size() == 0) {	
								History history = new History();
								history.setContent(result.getMessage());
								history.setSolution(relationship.getSolution());
								history.setRelationship(relationship.getKey());
								history.setFile(result.getFile());
								history.setFixedLink(result.getFixedLink());
								history.setLink(result.getLink());
								history.setState(History.stat.WAIT.name());
								history.pushCreatDate();
								ModelUtil.save(history);
								
								Queue queue = new Queue();
								queue.setHistory(history.getKey());
								queue.setConsumer(consumer.getKey());
								queue.setSolution(relationship.getSolution());
								queue.setRelationship(relationship.getKey());
								queue.setMessage(result.getMessage());
								queue.setFile(result.getFile());
								queue.setLink(result.getLink());
								queue.setFixedLink(result.getFixedLink());
								queue.pushCreatDate();
								ModelUtil.save(queue);
							}
						}
					}
				}
			}
		}
		
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		com.google.appengine.api.taskqueue.Queue queue = QueueFactory.getQueue("get");
		try {
		    Transaction txn = ds.beginTransaction();
		    queue.add(TaskOptions.Builder.withUrl("/cron/get").method(TaskOptions.Method.GET).countdownMillis(1000 * 45));
		    txn.commit();		    
		} catch (DatastoreFailureException exception) {
			LogUtil.error(
					LogUtil.TYPE.BATCH, 
					Getter.class, 
					null,
					LocalUtil.getResource("i-router.batch.common.unknown"), 
					exception
			);
		}
	}

}
